package com.zp.server.conf;

import com.zp.server.server.netty.handler.ConnectionCountHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author zhangpeng
 * @version 1.0.0
 * @date 2019/6/22 14:48
 * @since 1.0
 */
@Configuration
@RequiredArgsConstructor
@EnableConfigurationProperties(NettyConfProperties.class)
public class NettyConfiguration {


    private final NettyConfProperties nettyProperties;

    /**
     * ServerBootstrap
     *
     * @return
     */
    @Bean(name = "serverBootstrap")
    public ServerBootstrap bootstrap() {
        ServerBootstrap b = new ServerBootstrap();
        ConnectionCountHandler connectionCountHandler = new ConnectionCountHandler();
        b.group(bossGroup(), workerGroup())
                .channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.DEBUG))
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                        ChannelPipeline pipeline = ch.pipeline();
/*                // 添加心跳支持
                pipeline.addLast(new IdleStateHandler(120, 0, 0, TimeUnit.SECONDS));
                // 基于定长的方式解决粘包/拆包问题
//                    pipeline.addLast(new LengthFieldBasedFrameDecoder(max_frame_length
//                            , 0, 2, 0, 2));
//                    pipeline.addLast(new LengthFieldPrepender(2));
                //Delimiters.lineDelimiter()[0]
                pipeline.addLast(new DelimiterBasedFrameDecoder(Integer.MAX_VALUE, Delimiters.lineDelimiter()[0]));
                // 序列化
                //pipeline.addLast(new StringDecoder());  //new ObjectCodec()*/
                        pipeline.addLast(connectionCountHandler);
                    }
                });
        b.option(ChannelOption.SO_BACKLOG, nettyProperties.getBacklog());
        return b;
    }


    @Bean(destroyMethod = "shutdownGracefully")
    public NioEventLoopGroup bossGroup() {
        return new NioEventLoopGroup(nettyProperties.getBossCount());
    }

    @Bean(destroyMethod = "shutdownGracefully")
    public NioEventLoopGroup workerGroup() {
        return new NioEventLoopGroup(nettyProperties.getWorkerCount());
    }


}
